package cinvestav.adviseme.bean;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;

import org.springframework.security.context.SecurityContextHolder;

import cinvestav.adviseme.controller.PersonaController;
import cinvestav.adviseme.datamodel.Lugar;
import cinvestav.adviseme.datamodel.Persona;
import cinvestav.adviseme.util.DBException;
import cinvestav.adviseme.util.DataBaseDictionary;
import cinvestav.adviseme.util.SortableList;

import com.icesoft.faces.component.ext.RowSelectorEvent;

/**
*
* @author Javier Silva Pérez
*/
public class FindFriendViewBean extends SortableList{

	 //<editor-fold defaultstate="collapsed" desc="Atributos de Clase">
    protected PersonaController personaController;
    /**
     * Lista de Personas mostradas en la pagina
     */
    protected List<Persona> personas;
    /**
     * Persona Seleccionada
     */
    protected Persona personaSeleccionada;
    /**
     * Persona Modificar
     */
    protected Persona personaSeleccionadaModificar;
    /**
     * Valor del CheckBox para el filtro de ID
     */
    protected Boolean slctId;
    /**
     * Valor del CheckBox para el filtro de Nombre
     */
    protected Boolean slctNombre;
    /**
     * Valor del CheckBox para el filtro de Usuario
     */
    protected Boolean slctUsuario;
    /**
     * Valor del CheckBox para el filtro de Correo
     */
    protected Boolean slctCorreo;
    /**
     * Almacena los posibles mensajes de error
     */
    protected String errorMsg;
    /**
     * Texto insertado en el filtro de nombre
     */
    protected String nombreFiltro;
    /**
     * Texto insertado en el filtro de usuario
     */
    protected String usuarioFiltro;
    /**
     * Id insertado como filtro
     */
    protected String idFiltro;
    /**
     * Correo insertado como filtro
     */
    protected String correoFiltro;
    /**
     * Confirmacion para los diferentes paneles
     */
    private Boolean withConfirmation = true;
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="Metodos de Ordenamiento">
    /**
     * Metodo de ordenamiento, declara un comparador y ordena la lista deacuerdo a este
     */
    protected void sort() {
        if ((ascending != oldAscending)
                || (!sortColumnName.equals(oldSort))) {

            Comparator comparator = new Comparator() {

                public int compare(Object o1, Object o2) {
                    Persona c1 = (Persona) o1;
                    Persona c2 = (Persona) o2;
                    if (sortColumnName == null) {
                        return 0;
                    }
                    //Si la columna a ordenar es la de ID
                    if (sortColumnName.equals("idSort")) {
                        //Se pregunta si es orden ascendente o descendente
                        //y se compara el valor de los objetos en el ID
                        return ascending
                                ? Integer.valueOf(c1.getId()).compareTo(Integer.valueOf(c2.getId()))
                                : Integer.valueOf(c2.getId()).compareTo(Integer.valueOf(c1.getId()));
                    } else if (sortColumnName.equals("nombreSort")) {
                        //Si la columna a ordenar es la de nombre
                        //Se compara el nombre almacenado en los objetos
                        return ascending
                                ? c1.getNombreCompleto().compareTo(c2.getNombreCompleto())
                                : c2.getNombreCompleto().compareTo(c1.getNombreCompleto());
                    } else {
                        return 0;
                    }
                }
            };

            Collections.sort(personas, comparator);

            // reset dirty flags.
            oldAscending = ascending;
            oldSort = sortColumnName;
            for (Persona r : personas) {
                r.setSelected(false);
            }
            personaSeleccionada = new Persona();
        }
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="Gets y Sets">
    /**
     * Obtiene la lista de personas
     * @return  ArrayList con las personas
     */
    public List getPersonas() {
        sort();
        return personas;
    }

    /**
     * Get del ID
     * @return  True si el checkBox esta seleccionado, False de otra manera
     */
    public Boolean getSlctId() {
        return slctId;
    }

    /*
     * Establece el valor del CheckBox de la UI al Bean
     */
    public void setSlctId(Boolean slctId) {
        this.slctId = slctId;
    }

    /**
     * Obtiene el valor del ChackBox para el filtro Nombre
     * @return  True si esta seleccionado en la UI, false de otra manera
     */
    public Boolean getSlctNombre() {
        return slctNombre;
    }

    /**
     * Establece el valor del checkBox en el bean
     * @param slctNombre    Valor del checkBox en la UI
     */
    public void setSlctNombre(Boolean slctNombre) {
        this.slctNombre = slctNombre;
    }
    
    public Boolean getSlctUsuario() {
		return slctUsuario;
	}

	public void setSlctUsuario(Boolean slctUsuario) {
		this.slctUsuario = slctUsuario;
	}

	public Boolean getSlctCorreo() {
		return slctCorreo;
	}

	public void setSlctCorreo(Boolean slctCorreo) {
		this.slctCorreo = slctCorreo;
	}

	public String getNombreFiltro() {
		return nombreFiltro;
	}

	public void setNombreFiltro(String nombreFiltro) {
		this.nombreFiltro = nombreFiltro;
	}

	public String getUsuarioFiltro() {
		return usuarioFiltro;
	}

	public void setUsuarioFiltro(String usuarioFiltro) {
		this.usuarioFiltro = usuarioFiltro;
	}

	public String getCorreoFiltro() {
		return correoFiltro;
	}

	public void setCorreoFiltro(String correoFiltro) {
		this.correoFiltro = correoFiltro;
	}

	public void setPersonas(List<Persona> personas) {
		this.personas = personas;
	}

	/**
     * Set del Controlador de Persona de Autobuses, manda llamar al metodo de
     * inicializacion
     * @param personaController
     */
    public void setPersonaController(PersonaController personaController) {
        this.personaController = personaController;
        init();
    }
    
    public PersonaController getPersonaController() {
		return personaController;
	}


    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }

    public String getIdFiltro() {
        return idFiltro;
    }

    public void setIdFiltro(String idFiltro) {
        this.idFiltro = idFiltro;
    }

    public Persona getPersonaSeleccionada() {
        return personaSeleccionada;
    }

    public void setPersonaSeleccionada(Persona personaSeleccionada) {
        this.personaSeleccionada = personaSeleccionada;
    }

    public Boolean getWithConfirmation() {
        return withConfirmation;
    }

    public void setWithConfirmation(Boolean withConfirmation) {
        this.withConfirmation = withConfirmation;
    }

    public Persona getPersonaSeleccionadaModificar() {
        return personaSeleccionadaModificar;
    }

    public void setPersonaSeleccionadaModificar(Persona personaSeleccionadaModificar) {
        this.personaSeleccionadaModificar = personaSeleccionadaModificar;
    }

    //</editor-fold>
    /** Creates a new instance of PersonaBuscadorViewBean */
    public FindFriendViewBean() {
        super("idSort");
        personas = new LinkedList<Persona>();
        personaSeleccionada = new Persona();
        personaSeleccionadaModificar = new Persona();
        //personaController = new PersonaController();
    }

    /**
     * Inicializa la lista de todas las personas
     */
    public void init() {
        try {        	
            personas = personaController.getAll();
            slctId = Boolean.FALSE;
            slctNombre = Boolean.FALSE;
            slctCorreo = Boolean.FALSE;
            slctUsuario = Boolean.FALSE;
        } catch (DBException ex) {
            errorMsg = ex.getMessage();
        }
    }

    /**
     * Validacion para el ID, verifica que el numero debe ser Entero
     * @param context
     * @param validate
     * @param value
     */
    public void validaFormatoID(FacesContext context, UIComponent validate, Object value) {
        String id = (String) value;
        //Se verifica que el checkbox este seleccionado
        if (slctId) {
            //Se intenta convertir a entero, si hay un error, se coloca en el
            //mensaje designado para estoo
            try {
                Integer.parseInt(id);
            } catch (NumberFormatException ex) {
                ((UIInput) validate).setValid(false);
                FacesMessage msg = new FacesMessage("Solo se permiten digitos");
                context.addMessage(validate.getClientId(context), msg);
            }
        }
    }

    /**
     * Funcion que realiza la busqueda de amigos deacuerdo a los filtros
     * seleccionados en la interfaz
     */
    public String buscar() {
        /*
         * Mapa para los filtros seleccionados
         *      Key = Filtro a utilizar, definido en la clase "DataBaseDictionary"
         *      Value = Sera un arreglo de dos posiciones donde:
         *          [0] = Valor a buscar en la base (Valor del campo)
         *          [1] = Tipo de Dato, deacuerdo a este se realizara el set en el
         *                  PreparedStatement, Los tipos validos estan definidos en "DataBaseDictionary"
         */
    	String userID = "0";
    	String userName = SecurityContextHolder.getContext().getAuthentication().getName();
		if(userName!=null){
			userID = userName.substring(userName.lastIndexOf("@")+1);
		}
    	
    	Map<String,String[]> queryMap = new HashMap<String,String[]>();
    	String[] values = new String[3];
    	values[0] = userID;
		values[1] = DataBaseDictionary.COLUMN_TYPE_AMIGOSPORPERSONA_ID_LUGAR;  
		values[2] = DataBaseDictionary.ALIAS_AMIGOSPORPERSONA;
		queryMap.put(DataBaseDictionary.COLUMN_FILTRO_NAME_AMIGOSPORPERSONA_ID_PERSONA, values);
		
		if(slctId){
			values = new String[3];
			values[0] = idFiltro;
			values[1] = DataBaseDictionary.COLUMN_TYPE_PERSONA_ID;
			values[2] = DataBaseDictionary.ALIAS_PERSONA;
			queryMap.put(DataBaseDictionary.COLUMN_FILTER_NAME_PERSONA_ID, values);
		}
		if(slctNombre){
			values = new String[3];
			values[0] = nombreFiltro;
			values[1] = DataBaseDictionary.COLUMN_TYPE_PERSONA_NOMBREPERSONA;
			values[2] = DataBaseDictionary.ALIAS_PERSONA;
			queryMap.put(DataBaseDictionary.COLUMN_FILTER_NAME_PERSONA_NOMBREPERSONA, values);			
		}
		if(slctUsuario){
			values = new String[3];
			values[0] = usuarioFiltro;
			values[1] = DataBaseDictionary.COLUMN_TYPE_PERSONA_NOMBREUSUARIO_LIKE;
			values[2] = DataBaseDictionary.ALIAS_PERSONA;
			queryMap.put(DataBaseDictionary.COLUMN_FILTER_NAME_PERSONA_NOMBREUSUARIO_LIKE, values);
		}
		if(slctCorreo){
			values = new String[3];
			values[0] = correoFiltro;
			values[1] = DataBaseDictionary.COLUMN_TYPE_PERSONA_CORREO;
			values[2] = DataBaseDictionary.ALIAS_PERSONA;
			queryMap.put(DataBaseDictionary.COLUMN_FILTER_NAME_PERSONA_CORREO, values);			
		}
		try {
            //Se realiza la consulta
            personas = personaController.getByFilters(queryMap);
            personaSeleccionada = new Persona();
            personaSeleccionadaModificar = new Persona();
            errorMsg = "";            
        } catch (DBException ex) {
            //Si existe cualquier error, se muestra el mensaje de error al tipo
            errorMsg = ex.getMessage();
        }
        return "";
        /*Map<String, String[]> mapaConsulta = new HashMap<String, String[]>();
        String[] valor = new String[2];
        String filtro;
        //Si el filtro por ID esta seleccionado
        if (slctId) {
            //Se agrega una entrada al mapa
            valor = new String[2];
            valor[0] = idFiltro;
            valor[1] = DataBaseDictionary.COLUMN_TYPE_RUTA_ID;
            filtro = DataBaseDictionary.ALIAS_RUTA + "." + DataBaseDictionary.COLUMN_FILTRO_NOMBRE_RUTA_ID;
            mapaConsulta.put(filtro, valor);
        }

        //Si el filtro de Origen esta seleccionado
        if (slctOrigen) {
            //Se agrega una entrada al mapa
            valor = new String[2];
            valor[0] = origenFiltro;
            valor[1] = DataBaseDictionary.COLUMN_TYPE_LUGAR_NOMBRE;
            filtro = DataBaseDictionary.ALIAS_ORIGEN + "." + DataBaseDictionary.COLUMN_FILTRO_NAME_LUGAR_NOMBRE;
            mapaConsulta.put(filtro, valor);
        }

        //Si el filtro de Destino esta seleccionado
        if (slctDestino) {
            //Se agrega una entrada al mapa
            valor = new String[2];
            valor[0] = destinoFiltro;
            valor[1] = DataBaseDictionary.COLUMN_TYPE_LUGAR_NOMBRE;
            filtro = DataBaseDictionary.ALIAS_DESTINO + "." + DataBaseDictionary.COLUMN_FILTRO_NAME_LUGAR_NOMBRE;
            mapaConsulta.put(filtro, valor);
        }
        try {
            //Se realiza la consulta
            personas = personaController.getByFilters(mapaConsulta);
            personaSeleccionada = new Persona();
            personaSeleccionadaModificar = new Persona();
            errorMsg = "";
        } catch (DBException ex) {
            //Si existe cualquier error, se muestra el mensaje de error al usuario
            errorMsg = ex.getMessage();
        }*/
    }

    /**
     * SelectionListener esta relacionado con el componente  ice:rowSelector
     * es llamado cuando una fila es seleccionada en la UI
     *
     * @param event Evento del componente ice:rowSelector
     */
    public void rowSelectionListener(RowSelectorEvent event) {
        // build the new selected list
        /*Persona rutaAux;
        for (int i = 0, max = personas.size(); i < max; i++) {
            rutaAux = (Persona) personas.get(i);
            //Se ubica la linea seleccionada y se inicializa el objeto que la contendra
            if (rutaAux.isSelected()) {
                personaSeleccionada = new Persona((Persona) rutaAux);
                personaSeleccionadaModificar = new Persona((Persona) rutaAux);
            }
        }*/
    }

    /**
     * Modifica la informacion de la linea de autobus en la base de datos
     */
    public void modificar() {
        /*FacesContext context = FacesContext.getCurrentInstance();
        //Se valida que se haya seleccionado una linea en la tabla
        if (personaSeleccionadaModificar.getId() == null || personaSeleccionadaModificar.getId() == 0) {
            FacesMessage message = new FacesMessage();
            message.setSeverity(FacesMessage.SEVERITY_ERROR);
            message.setSummary("Debe seleccionar una ruta");
            message.setDetail("Debe seleccionar una ruta");
            context.addMessage("GeneralForm:icePnlTbSet:0:btnModificar", message);
            return;
        }
        try {

            //Se valida que el valor de nombre del origen no sea vacio
            if (personaSeleccionadaModificar.getOrigen().getNombre().isEmpty()) {
                FacesMessage message = new FacesMessage();
                message.setSeverity(FacesMessage.SEVERITY_ERROR);
                message.setSummary("No puede ser vacio");
                message.setDetail("No puede ser vacio");
                context.addMessage("GeneralForm:icePnlTbSet:0:txtOrigenPersona_Modificar", message);
                return;
            } else {
                List<ILugar> lugaresRes = lugarController.getByNombre(personaSeleccionadaModificar.getOrigen().getNombre());
                if (lugaresRes.isEmpty()) {
                    FacesMessage message = new FacesMessage();
                    message.setSeverity(FacesMessage.SEVERITY_ERROR);
                    message.setSummary("Lugar no válido");
                    message.setDetail("El lugar no existe en la base de datos");
                    context.addMessage("GeneralForm:icePnlTbSet:0:txtOrigenPersona_Modificar", message);
                    return;
                } else {
                    personaSeleccionadaModificar.setOrigen(lugaresRes.get(0));
                }
            }


            //Se valida que el valor de nombre del destino no sea vacio
            if (personaSeleccionadaModificar.getDestino().getNombre().isEmpty()) {
                FacesMessage message = new FacesMessage();
                message.setSeverity(FacesMessage.SEVERITY_ERROR);
                message.setSummary("No puede ser vacio");
                message.setDetail("No puede ser vacio");
                context.addMessage("GeneralForm:icePnlTbSet:0:txtDestinoPersona_Modificar", message);
                return;
            } else {
                List<ILugar> lugaresRes = lugarController.getByNombre(personaSeleccionadaModificar.getDestino().getNombre());
                if (lugaresRes.isEmpty()) {
                    FacesMessage message = new FacesMessage();
                    message.setSeverity(FacesMessage.SEVERITY_ERROR);
                    message.setSummary("Lugar no válido");
                    message.setDetail("El lugar no existe en la base de datos");
                    context.addMessage("GeneralForm:icePnlTbSet:0:txtDestinoPersona_Modificar", message);
                    return;
                } else {
                    personaSeleccionadaModificar.setDestino(lugaresRes.get(0));
                }
            }

            //Se realiza la actualizacion en la base;
            personaController.update(personaSeleccionadaModificar);
            buscar();
        } catch (DBException ex) {
            FacesMessage msg = new FacesMessage(ex.getMessage() + ex.getErrorConsulta().getMessage());
            context.addMessage("GeneralForm:icePnlTbSet:0:btnModificar", msg);
        }*/
    }

    /**
     * Eliminar la fila seleccionada de la base de datos
     */
    public void eliminar() {
        /*FacesContext context = FacesContext.getCurrentInstance();
        //Se valida que se haya seleccionado una Persona en la tabla
        if (personaSeleccionada.getId() == null || personaSeleccionada.getId() == 0) {
            FacesMessage message = new FacesMessage();
            message.setSeverity(FacesMessage.SEVERITY_ERROR);
            message.setSummary("Debe seleccionar una Persona");
            message.setDetail("Debe seleccionar una Persona");
            context.addMessage("GeneralForm:icePnlTbSet:0:btnEliminar_Baja", message);
            return;
        }
        try {
            //Se realiza la actualizacion en la base;
            personaController.delete(personaSeleccionada);
            buscar();
        } catch (DBException ex) {
            FacesMessage msg = new FacesMessage(ex.getMessage() + ex.getErrorConsulta().getMessage());
            context.addMessage("GeneralForm:icePnlTbSet:0:btnEliminar_Baja", msg);
        }*/
    }
}
